package com.nifostasky.comic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nifostasky.comic.entitys.SysMenu;
import com.nifostasky.comic.entitys.SysRole;
import com.nifostasky.comic.entitys.SysRoleMenu;
import com.nifostasky.comic.exceptions.BusinessException;
import com.nifostasky.comic.mapper.SysUserMapper;
import com.nifostasky.comic.service.SysMenuService;
import com.nifostasky.comic.service.SysRoleMenuService;
import com.nifostasky.comic.service.SysRoleService;
import com.nifostasky.comic.dtos.MenuDTO;
import com.nifostasky.comic.mapper.SysRoleMapper;
import com.nifostasky.comic.utils.PageUtils;
import com.nifostasky.comic.vos.ResultCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysMenuService sysMenuService;


    @Override
    public IPage<SysRole> findListPage(PageUtils pageUtils, SysRole sysRole) {
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(sysRole.getRoleName()), SysRole::getRoleName, sysRole.getRoleName());
        queryWrapper.eq(StringUtils.isNotBlank(sysRole.getRoleCode()), SysRole::getRoleCode, sysRole.getRoleCode());
        queryWrapper.eq(Objects.nonNull(sysRole.getState()), SysRole::getState, sysRole.getState());
        queryWrapper.orderByAsc(SysRole::getSort).orderByDesc(SysRole::getCreateDate);
        IPage<SysRole> page = this.baseMapper.selectPage(new Page<>(pageUtils.getPageIndex(), pageUtils.getPageSize()), queryWrapper);
        return page;
    }

    @Override
    public List<MenuDTO> getMenusByRole(Long roleId) {
        List<SysMenu> menus = sysUserMapper.findMenuByRoleId(roleId);
        if (CollectionUtils.isEmpty(menus)) {
            return null;
        }
        List<MenuDTO> menuDTOS = new ArrayList<>();
        Set<Long> listParentId = new HashSet<>();
        menus.forEach(menu -> {
            MenuDTO dto = new MenuDTO();
            BeanUtils.copyProperties(menu, dto);
            listParentId.add(menu.getParentId());
            menuDTOS.add(dto);
        });
        List<Long> listMenuId = menus.stream().map(m -> m.getId()).collect(Collectors.toList());
        List<Long> diffListMenuId = listMenuId.stream().filter(id -> !listParentId.contains(id)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(diffListMenuId)) {
            List<SysMenu> diffMenus = sysMenuService.findDataListByIds(diffListMenuId);
            if (CollectionUtils.isNotEmpty(diffMenus)) {
                List<MenuDTO> diffMenuTto = new ArrayList<>();
                for (SysMenu m : diffMenus) {
                    MenuDTO dto = new MenuDTO();
                    BeanUtils.copyProperties(m, dto);
                    diffMenuTto.add(dto);
                }
                menuDTOS.addAll(diffMenuTto);
            }
        }
        List<MenuDTO> listMenu = menuDTOS.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MenuDTO::getMenuCode))), ArrayList::new));
        this.findParentDto(listMenu);
        return listMenu.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MenuDTO::getMenuCode))), ArrayList::new));
    }

    private void findParentDto(List<MenuDTO> listMenuDto) {
        this.findParentById(listMenuDto);
    }

    private List<MenuDTO> findParentById(List<MenuDTO> listMenuDto) {
        if (CollectionUtils.isNotEmpty(listMenuDto)) {
            List<MenuDTO> newList = new ArrayList<>();
            List<Long> listMenuId = listMenuDto.stream().map(MenuDTO::getParentId).collect(Collectors.toList());
            List<SysMenu> listMenu = sysMenuService.findDataListByIds(listMenuId);
            if (CollectionUtils.isNotEmpty(listMenu)) {
                for (SysMenu m : listMenu) {
                    MenuDTO dto = new MenuDTO();
                    BeanUtils.copyProperties(m, dto);
                    newList.add(dto);
                }
            }
            if (CollectionUtils.isNotEmpty(newList)) {
                listMenuDto.addAll(newList);
                return findParentById(newList);
            }
        }
        return null;
    }

    @Override
    public List<Long> getRoleMenuByRoleId(Long roleId) {
        return sysRoleMenuService.getRoleMenuByRoleId(roleId);
    }

    @Override
    @Transactional
    public Boolean setRoleMenu(Long roleId, String menuIds) {
        if (Objects.isNull(roleId) || StringUtils.isBlank(menuIds)) {
            throw new BusinessException("缺少必填参数");
        }
        List<Long> listMenuId = Arrays.asList(menuIds.split(",")).stream()
                .map(menuId -> Long.parseLong(menuId)).collect(Collectors.toList());
        sysRoleMenuService.deleteRoleMenuRelByRoleId(roleId);
        List<SysRoleMenu> listRoleMenu = new ArrayList<>();
        for (Long menuId : listMenuId) {
            SysRoleMenu sysUserRole = new SysRoleMenu();
            sysUserRole.setMenuId(menuId);
            sysUserRole.setRoleId(roleId);
            listRoleMenu.add(sysUserRole);
        }
        return sysRoleMenuService.saveBatch(listRoleMenu);
    }

    @Override
    @Transactional
    public Boolean deleteRoleAllById(String ids) {
        if (StringUtils.isBlank(ids)) {
            throw new BusinessException(ResultCode.REQUIRED_PARAMS);
        }
        List<String> listId = Arrays.asList(ids.split(","));
        listId.forEach(roleId -> {
            sysRoleMenuService.deleteRoleMenuRelByRoleId(Long.parseLong(roleId));
        });
        return this.removeByIds(listId);
    }
}
